Bug 469868 - Filenames with colon ":" are not saved correctly
authorTor Lillqvist <tml@novell.com>
Tue, 11 Mar 2008 18:43:49 +0000 (18:43 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Tue, 11 Mar 2008 18:43:49 +0000 (18:43 +0000)
2008-03-11  Tor Lillqvist  <tml@novell.com>

Bug 469868 - Filenames with colon ":" are not saved correctly

* gtk/gtkfilechooserentry.c (insert_text_callback)
(delete_text_callback) [Win32]: New functions to make sure that
colons used otherwise than as a separator after a drive letter, or
characters that are always illegal in file names, are rejected on
input. This means that the GTK+ file chooser can't be used to
input full names of alternate data streams, but oh well. There are
still more checks that could be done on the file names, see the
bug report. But this will do for now.
(_gtk_file_chooser_entry_init) [Win32]: Connect above functions.

svn path=/trunk/; revision=19753

ChangeLog
gtk/gtkfilechooserentry.c

index 24691eb2b528a0db6e2736e4541f38c0da98ab61..adcd947e0345303480931ad079c8dbdc64731a59 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2008-03-11  Tor Lillqvist  <tml@novell.com>
+
+       Bug 469868 - Filenames with colon ":" are not saved correctly
+
+       * gtk/gtkfilechooserentry.c (insert_text_callback)
+       (delete_text_callback) [Win32]: New functions to make sure that
+       colons used otherwise than as a separator after a drive letter, or
+       characters that are always illegal in file names, are rejected on
+       input. This means that the GTK+ file chooser can't be used to
+       input full names of alternate data streams, but oh well. There are
+       still more checks that could be done on the file names, see the
+       bug report. But this will do for now.
+       (_gtk_file_chooser_entry_init) [Win32]: Connect above functions.
+
 2008-03-11  Jordi Mallach  <jordi@sindominio.net>
 
        * configure.in (ALL_LINGUAS): Add ca@valencia (Valencian-Catalan).
index 3704ccabcee98a93ad8e23595632b21b0d54b9a2..e68248d987e29a005f8336569d7d3ac9f2ae6cce 100644 (file)
@@ -87,6 +87,19 @@ static void     gtk_file_chooser_entry_do_insert_text (GtkEditable *editable,
 
 static void     clear_completion_callback (GtkFileChooserEntry *chooser_entry,
                                           GParamSpec          *pspec);
+
+#ifdef G_OS_WIN32
+static gint     insert_text_callback      (GtkFileChooserEntry *widget,
+                                          const gchar         *new_text,
+                                          gint                 new_text_length,
+                                          gint                *position,
+                                          gpointer             user_data);
+static void     delete_text_callback      (GtkFileChooserEntry *widget,
+                                          gint                 start_pos,
+                                          gint                 end_pos,
+                                          gpointer             user_data);
+#endif
+
 static gboolean match_selected_callback   (GtkEntryCompletion  *completion,
                                           GtkTreeModel        *model,
                                           GtkTreeIter         *iter,
@@ -169,6 +182,13 @@ _gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
                    G_CALLBACK (clear_completion_callback), NULL);
   g_signal_connect (chooser_entry, "notify::selection-bound",
                    G_CALLBACK (clear_completion_callback), NULL);
+
+#ifdef G_OS_WIN32
+  g_signal_connect (chooser_entry, "insert_text",
+                   G_CALLBACK (insert_text_callback), NULL);
+  g_signal_connect (chooser_entry, "delete_text",
+                   G_CALLBACK (delete_text_callback), NULL);
+#endif
 }
 
 static void
@@ -876,6 +896,70 @@ clear_completion_callback (GtkFileChooserEntry *chooser_entry,
     }
 }
 
+#ifdef G_OS_WIN32
+static gint
+insert_text_callback (GtkFileChooserEntry *chooser_entry,
+                     const gchar         *new_text,
+                     gint                 new_text_length,
+                     gint                *position,
+                     gpointer             user_data)
+{
+  const gchar *colon = memchr (new_text, ':', new_text_length);
+  gint i;
+
+  /* Disallow these characters altogether */
+  for (i = 0; i < new_text_length; i++)
+    {
+      if (new_text[i] == '<' ||
+         new_text[i] == '>' ||
+         new_text[i] == '"' ||
+         new_text[i] == '|' ||
+         new_text[i] == '*' ||
+         new_text[i] == '?')
+       break;
+    }
+
+  if (i < new_text_length ||
+      /* Disallow entering text that would cause a colon to be anywhere except
+       * after a drive letter.
+       */
+      (colon != NULL &&
+       *position + (colon - new_text) != 1) ||
+      (new_text_length > 0 &&
+       *position <= 1 &&
+       GTK_ENTRY (chooser_entry)->text_length >= 2 &&
+       gtk_entry_get_text (GTK_ENTRY (chooser_entry))[1] == ':'))
+    {
+      gtk_widget_error_bell (GTK_WIDGET (chooser_entry));
+      g_signal_stop_emission_by_name (chooser_entry, "insert_text");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+delete_text_callback (GtkFileChooserEntry *chooser_entry,
+                     gint                 start_pos,
+                     gint                 end_pos,
+                     gpointer             user_data)
+{
+  /* If deleting a drive letter, delete the colon, too */
+  if (start_pos == 0 && end_pos == 1 &&
+      GTK_ENTRY (chooser_entry)->text_length >= 2 &&
+      gtk_entry_get_text (GTK_ENTRY (chooser_entry))[1] == ':')
+    {
+      g_signal_handlers_block_by_func (chooser_entry,
+                                      G_CALLBACK (delete_text_callback),
+                                      user_data);
+      gtk_editable_delete_text (GTK_EDITABLE (chooser_entry), 0, 1);
+      g_signal_handlers_unblock_by_func (chooser_entry,
+                                        G_CALLBACK (delete_text_callback),
+                                        user_data);
+    }
+}
+#endif
+
 /**
  * _gtk_file_chooser_entry_new:
  * @eat_tabs: If %FALSE, allow focus navigation with the tab key.